package order;

import address.Address;
import address.City;
import address.Community;
import enums.LogisticsStatus;
import enums.OrderStatus;
import enums.OrderType;
import enums.PaymentType;
import models.BaseModel;
import models.admin.AdminUser;
import models.constants.DeletedStatus;
import models.merchant.Merchant;
import models.weixin.WebUser;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import play.Logger;
import util.common.ConvertUtil;
import util.common.DateUtil;
import util.list.ListUtil;
import util.list.models.EasyUIColumn;

import javax.persistence.*;
import java.util.*;

/**
 * Created by liming on 16/7/18.
 */
@Entity
@Table(name = "admin_order")
public class AdminOrder extends BaseModel {

    /**
     * 订单信息
     */
    @ManyToOne
    @JoinColumn(name = "order_id")
    public Order order;

    /**
     * 订单号
     */
    @Column(name = "order_no")
    public String orderNumber;

    /**
     * 后台订单编号
     */
    @Column(name = "code")
    public String code;

    /**
     * 防止后退刷新一直添加订单
     */
    @Column(name = "uuid")
    public String uuid;

    /**
     * 订单名称
     */
    @Column(name = "name")
    public String name;

    /**
     * 下单用户
     */
    @JoinColumn(name = "web_user_id", nullable = true)
    @ManyToOne
    public WebUser webUser;

    /**
     * 下单用户 所属业务员
     */
    @JoinColumn(name = "sale_man_user_id", nullable = true)
    @ManyToOne
    public WebUser saleManUser;

    /**
     * 所属商户
     */
    @JoinColumn(name = "fee_merchant_id", nullable = true)
    @ManyToOne
    public Merchant merchant;

    /**
     * 配送地址
     */
    @JoinColumn(name = "address_id", nullable = true)
    @ManyToOne
    public Address address;

    /**
     * 订单总金额
     */
    @Column(name = "amount")
    public Double amount = 0D;

    /**
     * 订单折扣金额  比如活动折扣 使用优惠券金额
     */
    @Column(name = "discount_pay")
    public Double discountPay = 0D;

    /**
     * 已支付金额 实际支付金额
     */
    @Column(name = "paymented_amount")
    public Double paymentedAmount = 0D;

    /**
     * 合伙人金额
     */
    @Column(name = "partner_amount")
    public Double partnerAmount = 0D;

    /**
     * 支付的运费
     */
    @Column(name = "freight")
    public Double freight = 0D;

    /**
     * 已退款金额
     */
    @Column(name = "refunded_amount")
    public Double refundedAmount;

    /**
     * 订单支付状态
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "status")
    public OrderStatus status;

    /**
     * 订单类型
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "order_type")
    public OrderType type;

    /**
     * 是否正式进行跟踪
     */
    @Column(name = "to_track")
    public Boolean toTrack;

    /**
     * 订单备注信息
     */
    @Column(name = "remark")
    public String remark;

    /**
     * 付款时间
     */
    @Column(name = "payed_at")
    public Date payedAt;

    /**
     * 创建时间
     */
    @Column(name = "created_at")
    public Date createdAt;

    /**
     * 逻辑删除,0:未删除，1:已删除
     */
    @Enumerated(EnumType.ORDINAL)
    public DeletedStatus deleted;

    @Transient
    public List<OrderItem> orderItems;

    /**
     * 后台订单状态:
     */
    //出库驳回 10
    public final static Integer OS_REJECT = 10;

    //新订单 20
    public final static Integer OS_NEW = 20;

    //已生成出库单 30
    public final static Integer OS_READY = 30;

    //出库单提交 40
    public final static Integer OS_SUBMIT = 40;

    //已出库 50
    public final static Integer OS_OUT = 50;

    //未出库退回 100
    public final static Integer OS_NO_OUT_RETRUN = 100;

    @Column(name = "admin_order_status")
    public Integer adminOrderStatus = OS_NEW;

    /**
     * 物流状态:
     * 备货中
     * 已配货
     * 未送达退回
     * 物流扫描
     * 已发货
     * 已送达
     */
    @Column(name = "logistics_status")
    @Enumerated(EnumType.STRING)
    public LogisticsStatus logisticsStatus = LogisticsStatus.PREPARING;

    /**
     * 打包人
     */
    @ManyToOne
    @JoinColumn(name = "package_user_id")
    public AdminUser packageUser;

    /**
     * 打包时间
     */
    @Column(name = "package_date")
    @Temporal(TemporalType.TIMESTAMP)
    public Date packageDate;

    /**
     * 打包日期
     */
    @Column(name = "package_day")
    @Temporal(TemporalType.DATE)
    public Date packageDay;

    /**
     * 打包重量
     */
    @Column(name = "weight")
    public Double weight;

    /**
     * 快递员
     */
    @ManyToOne
    @JoinColumn(name = "courier_id")
    public AdminUser courier;

    /**
     * 快递扫描时间
     */
    @Column(name = "scan_date")
    @Temporal(TemporalType.TIMESTAMP)
    public Date scanDate;

    /**
     * 快递出发时间
     */
    @Column(name = "go_date")
    @Temporal(TemporalType.TIMESTAMP)
    public Date goDate;

    /**
     * 快递送达时间
     */
    @Column(name = "arrive_date")
    @Temporal(TemporalType.TIMESTAMP)
    public Date arriveDate;

    /**
     * 是否使用临时地址
     */
    @Column(name = "use_temp_address")
    public Boolean useTempAddress = false;

    /**
     * 临时配送区域
     */
    @JoinColumn(name = "temp_city_id")
    @ManyToOne
    public City tempCity;

    /**
     * 临时配送区域
     */
    @ManyToOne
    @JoinColumn(name = "temp_community_id")
    public Community tempCommunity;

    /**
     * 临时客户名称
     */
    @Column(name = "temp_user_name")
    public String tempUserName;

    /**
     * 临时联系电话
     */
    @Column(name = "temp_phone")
    public String tempPhone;

    /**
     * 支付类型
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "payment_type")
    public PaymentType paymentType;

    /**
     * 地址
     */
    @Column(name = "temp_address")
    public String tempAddress;

    /**
     * 出库单ID
     */
    @Column(name = "admin_stock_out_id")
    public Long adminStockOutId;

    /**
     * 出库单编号
     */
    @Column(name = "admin_stock_out_code")
    public String adminStockOutCode;

    /**
     * 收款人姓名
     */
    @Column(name = "collect_user_name")
    public String collectUserName;

    /**
     * 标记颜色
     */
    @Column(name = "mark_color")
    public String markColor;

    /**
     * 出库单打印序号
     */
    @Transient
    public Integer printOrder;

    /**
     * 订单打印包装订单明细使用
     */
    @Transient
    public List<Map<String,Object>> adminOrderItemList;

    /**
     * 为了解决订单明细超过12的情况将订单明细转化后放入到此对象中
     */
    @Transient
    public List<List<Map<String, Object>>> adminOrderItemPages;

    /**
     * 版本号
     */
    @Version
    public Integer version = 0;

    public AdminOrder() {
        super();
    }

    public AdminOrder(Order order) {
        this.order = order;
        this.merchant = order.merchant;
        this.address = order.address;
        this.webUser = order.webUser;
        this.name = order.name;
        this.uuid = order.uuid;
        this.orderNumber = order.orderNumber;

        this.amount = order.amount == null?0:order.amount;
        this.discountPay = order.discountPay == null?0:order.discountPay;
        this.paymentedAmount = order.paymentedAmount == null?0:order.paymentedAmount;
        this.partnerAmount = order.partnerAmount == null?0:order.partnerAmount;
        this.freight = order.freight == null?0:order.freight;
        this.refundedAmount = order.refundedAmount == null?0:order.refundedAmount;

        this.status = order.status;
        this.type = order.type;
        this.remark = order.remark;
        this.payedAt = order.payedAt;
        this.createdAt = order.createdAt;
        this.createAt = order.createdAt;
        this.deleted = order.deleted;
        this.paymentType = order.paymentType;
        this.saleManUser = order.saleManUser != null ? order.saleManUser : null ;
        //加载erp编号
        if(this.id == null){
            this.loadKey();
        }
    }

    /**
     * 根据订单查询 拆分订单
     *
     * @param order
     * @return
     */
    public static AdminOrder findByOrder(Order order) {
        return find("order = ? and deleted = ?", order, DeletedStatus.UN_DELETED).first();
    }


    /**
     * 根据订单查询 拆分订单
     *
     * @param order
     * @return
     */
    public static AdminOrder findByRepairOrder(Order order) {
        return find("order = ?", order).first();
    }

    /**
     * 加载出库单弹出订单
     * @param page
     * @param rows
     * @param sort
     * @param order
     * @param filterRules
     * @return
     */
    private final static String SQL_STOCK_OUT_ORDER =
            "select  a.id,a.paymented_amount,a.fee_merchant_id,a.mark_color," +
                    "c.name as merchant_name," +
                    "a.code," +
                    "a.create_at," +
                    "if(a.use_temp_address = 1,a.temp_user_name,b.user_name) as user_name," +
                    "if(a.use_temp_address = 1,a.temp_phone,b.phone) as phone," +
                    "if(a.use_temp_address = 1,f.name,g.name) as city_name," +
                    "if(a.use_temp_address = 1,e.name,d.name) as community_name," +
                    "a.logistics_status," +
                    "h.name," +
                    "h.phone_no," +
                    "a.remark" +
            " from admin_order a" +
            " left join address b on a.address_id = b.id" +
            " left join power_merchants c on a.fee_merchant_id = c.id" +
            " left join address_community d on b.confirm_community_id = d.id" +
            " left join address_community e on a.temp_community_id = e.id" +
            " left join address_citys f on a.temp_city_id = f.id" +
            " left join address_citys g on b.confirm_city_id = g.id" +
            " left join admin_user h on a.courier_id = h.id" +
            " where a.deleted = 0 and a.admin_order_status <=  20 and a.to_track = 1" +
            " and (a.use_temp_address = 1 or (a.use_temp_address = 0 and b.is_confirm = 1))" +
            " and a.fee_merchant_id in (select aum.merchant_id from admin_user_merchant aum where aum.admin_user_id = %d)" +
            " order by a.admin_order_status,a.id";
    public static Map<String,Object> loadStockOutOrder(int page,
                                              int rows,
                                              String sort,
                                              String order,
                                              String filterRules,
                                              AdminUser adminUser){
        Map<String,Object> resultMap = new HashMap<>();
        String sql = "select * from (%s) a %s LIMIT %d,%d";
        String sqlCount = "select count(1) from (%s) a %s";
        String sqlWhere = ListUtil.initWhereOrderStr(null, filterRules, null , sort, order);
        String sqlCountWhere = ListUtil.initWhereStr(null, filterRules);
        String sqlMain = String.format(SQL_STOCK_OUT_ORDER,adminUser.getId());
        sqlWhere = sqlWhere.length()>0?"where " + sqlWhere:"";
        sqlCountWhere = sqlCountWhere.length()>0?"where " + sqlCountWhere:"";
        Query query = em().createNativeQuery(String.format(sql,sqlMain, sqlWhere,(page-1)*rows,rows));
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map<String, Object>> resultList = query.getResultList();
        Long count = ConvertUtil.toLong(em().createNativeQuery(String.format(sqlCount,sqlMain,sqlCountWhere)).getSingleResult());
        EasyUIColumn[] easyUIColumns = new EasyUIColumn[]{
                new EasyUIColumn("mark_color", "", 20,"fmMarkColor"),
                new EasyUIColumn("merchant_name", "商户名称", 100),
                new EasyUIColumn("code", "订单编号", 130),
                new EasyUIColumn("create_at", "订单时间", 130),
                new EasyUIColumn("user_name", "客户名称", 90),
                new EasyUIColumn("phone", "联系电话", 100),
                new EasyUIColumn("city_name", "区域", 90),
                new EasyUIColumn("community_name", "社区", 150),
                new EasyUIColumn("remark", "备注", 250)
        };

        resultMap.put("rows", resultList);
        resultMap.put("total", count);
        resultMap.put("columns", easyUIColumns);
        return resultMap;

    }

    /**
     * 报表获取销售订单汇总数据
     */
    public final static String SQL_ORDER_SUMMARY = "select sum(ifnull(a.discount_pay,0)) as discount_pay,sum(ifnull(a.freight,0)) as freight from admin_order a where a.deleted = 0 and a.admin_order_status<100 and to_track = 1 %s";
    public static List<Map<String,Object>> loadAdminOrderSummary(
            String beginDate,
            String endDate,
            Long merchantId
    ){
        String where="";
        if(beginDate!=null)
            where += " and a.create_at>='" + ConvertUtil.escapeSql(beginDate) + "'";
        if(endDate!=null)
            where += " and a.create_at<'" + ConvertUtil.escapeSql(endDate) + "'";
        if(merchantId !=null)
            where += " and a.fee_merchant_id=" + merchantId;
        Query query = em().createNativeQuery(String.format(SQL_ORDER_SUMMARY,where));
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return  query.getResultList();
    }

    /**
     * 出库单提交 更新订单状态
     * 同一出库单的订单,出库操作后,有部分订单的订单状态并未被更改为出库,暂时没有找到确切的原因
     * 因为出现的条件不确定,暂时更改修改状态的方法,不用原生sql的方法
     *
     * @param stockOutId
     */
    private final static String SQL_SUBMIT_STOCK_OUT_ORDER= "update admin_order set admin_order_status = ? where admin_stock_out_id = ?";
    public static void updateOrderStatus(long stockOutId,Integer status){
        Logger.info("LOGGER updateOrderStatus -------------------出库单提交 更新adminOrder订单状态 ");
        List<AdminOrder> adminOrderList = AdminOrder.find("adminStockOutId = ? " , stockOutId).fetch();
        if(adminOrderList != null && adminOrderList.size() > 0) {
            for (AdminOrder adminOrder : adminOrderList) {
                adminOrder.adminOrderStatus = status;
                adminOrder.save();

            }
        }

//        em().createNativeQuery(SQL_SUBMIT_STOCK_OUT_ORDER).setParameter(1,status).setParameter(2,stockOutId).executeUpdate();
    }

    /**
     * 根据出库单ID查询订单信息
     * @param stockOutId
     * @return
     */
    public static List<AdminOrder> findByStockOutId(long stockOutId){
        return AdminOrder.find("adminStockOutId = ?",stockOutId).fetch();
    }
    /**
     * 根据订单ID查询订单
     * * @param id
     * @return
     */
    public static AdminOrder findByAdminOrderId(Long id) {
        return AdminOrder.find("id=? and deleted=?", id, DeletedStatus.UN_DELETED).first();
    }
    public  static List<AdminOrder> loadALLAdminorder(){
        return AdminOrder.find("deleted=?", DeletedStatus.UN_DELETED).fetch();
    }


    /**
     * 统计用户在某一时间段内的消费金额
     * 数据来源: adminOrder 关联的order的订单金额
     * @param webUserId
     * @param startAt
     * @return
     */
    public static Double countUserOrderAmount(long webUserId , String startAt){
        String sqlSelect = "SELECT round(ifnull(sum(ifnull(a.amount,0)),0),2) as total_amount ,   " +
                "  round(ifnull(sum(ifnull(a.paymented_amount,2)),0),2) as payment_amount   " +
                "  from orders a   " +
                "  left join admin_order b on a.id = b.order_id  " +
                "  where b.to_track = 1 and b.deleted = 0 and b.admin_order_status < 100  and a.web_user_id = "+webUserId+" and a.created_at >= '"+startAt+"'";
        Double orderAmpunt = 0d ;

        Query query = AdminOrder.em().createNativeQuery(sqlSelect);
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map<String , Object>> resultList = query.getResultList();
        if(resultList != null && resultList.size() > 0 && resultList.get(0)!= null){
            orderAmpunt = ConvertUtil.toDouble(resultList.get(0).get("total_amount"));
        }

        return orderAmpunt ;
    }

    /**
     * 根据订单id 查询订单集合
     * 当IDS为空或者长度为0时会报错,所以使用该方法之前需判断ids
     * @param ids
     * @return
     */
    public static List<AdminOrder> findByIds(String ids){
        return AdminOrder.find("id in ("+ids+")" ).fetch();
    }

    /**
     * 加载业务员客户当日订单量
     * @param saleManUser
     * @return
     */
    public static List<AdminOrder> loadBySaleManAndCurrentDate(WebUser saleManUser){
        return AdminOrder.find("deleted = ?1 and toTrack = ?2 and createAt >= ?" , DeletedStatus.UN_DELETED , 1 , DateUtil.getBeginOfDay()).fetch();
    }

}
